package org.third.integration.etcd.utils;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ConnectionPoolTimeoutException;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.third.common.SS_CONSTANT;
import org.third.common.exception.RequestTimeoutException;
import org.third.common.exception.ServiceUnavailableException;
import org.third.common.utils.EnvUtils;
import org.third.common.utils.HttpClientUtils;

import java.io.IOException;
import java.net.SocketTimeoutException;

@Component
public class EtcdWathcer {
	
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	
	private CloseableHttpClient httpclientWatcher = HttpClientUtils.getCertificateIngnoredAndWithClientCertificateHttpClient(
			EnvUtils.getEtcdclientcertificatefile(), EnvUtils.getEtcdclientcertificatepwd(), SS_CONSTANT.ETCD_WATCHER_MAX_CONNECTION);
	
	public StringBuffer watchEtcdValue(String fullUrl){
		
		StringBuffer responseBody = null;
		CloseableHttpResponse response = null;
		
		HttpGet httpGet = new HttpGet(fullUrl);
		//http://stackoverflow.com/questions/6764035/apache-httpclient-timeout
		RequestConfig requestConfig = RequestConfig.custom()
				  .setConnectionRequestTimeout(SS_CONSTANT.ETCD_WATCHER_CONNECTION_TIMEOUT_IN_SECONDS * 1000)
				  .setSocketTimeout(SS_CONSTANT.ETCD_WATCHER_MAX_TIMEOUT_IN_SECONDS * 1000)
				  .build();
		httpGet.setConfig(requestConfig);
		
		try {
			//ConnectionPoolTimeoutException
			response = httpclientWatcher.execute(httpGet);
			HttpEntity entity = response.getEntity();
			logger.info("Going to watch etcd key [{}]", fullUrl);
			//SocketTimeoutException
			responseBody = new StringBuffer(IOUtils.toString(entity.getContent(), "UTF-8"));
			EntityUtils.consume(entity);
		} catch(ConnectionPoolTimeoutException cpte){
			logger.info("Reject to watch etcd key [{}], current service is busy", fullUrl);
			String errMsg = String.format("Current service is busy, already have [%s] etcd keys to watch", SS_CONSTANT.ETCD_WATCHER_MAX_CONNECTION); 
			throw new ServiceUnavailableException(errMsg);
		} catch(SocketTimeoutException ste){
			String errMsg = String.format("Timeout when watching etcd key [%s]", fullUrl); 
			throw new RequestTimeoutException(errMsg);
		} catch (Exception e) {
			String errMsg = String.format("Failed to request key [%s]", fullUrl);  
			throw new RuntimeException(errMsg, e);
		}finally{
			if(response != null){
				try {
					response.close();
				} catch (IOException e) {
					logger.warn("something wrong when closing response.", e);
				}
			}
		}
	    
		return responseBody;
	}
	
}
